package pl.kaczmarz.audiosteganography;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

/**
 *
 * @author Pawel
 */
public class Decoder extends SwingWorker<Void, Void> {

	private String inputFileName;
	private String outputFileName;
	private String keyFileName;

	private JTextArea consoleOut;

	public String getInputFileName() {
		return inputFileName;
	}

	public void setInputFileName(String inputFileName) {
		this.inputFileName = inputFileName;
	}

	public String getOutputFileName() {
		return outputFileName;
	}

	public void setOutputFileName(String outputFileName) {
		this.outputFileName = outputFileName;
	}

	public void setConsoleOut(JTextArea consoleOut) {
		this.consoleOut = consoleOut;
	}

	public String getKeyFileName() {
		return keyFileName;
	}

	public void setKeyFileName(String keyFileName) {
		this.keyFileName = keyFileName;
	}

	public JTextArea getConsoleOut() {
		return consoleOut;
	}

	public Void doInBackground() {
		return decode();
	}

	public Void decode() {

		if (consoleOut != null) {
			consoleOut.setText("");
			consoleOut.append("Trwa dekodowanie wiadomości...\n");
		}

		setProgress(0);

		try (WaveFile inputFile = WaveFile.open(inputFileName, "r")) {

			KeyFile key = KeyFile.load(keyFileName);

			int messageLength = key.getMessageLength();

			int zeroDelayBlocks = inputFile.milisecondsToBlocks(key.getZeroDelay());
			int oneDelayBlocks = inputFile.milisecondsToBlocks(key.getOneDelay());
			int blockLengthBlocks = inputFile.milisecondsToBlocks(key.getBlockLength());
			boolean[] messageBits = new boolean[messageLength];

			int[] samples = new int[blockLengthBlocks];

			for (int bit = 0; bit < messageBits.length; ++bit) {

				double zeroAcorr = 0;
				double oneAcorr = 0;

				for (int iter = 0; iter < key.getMessageRepeat(); ++iter) {
					for (int ch = 0; ch < inputFile.getNumberOfChannels(); ++ch) {
						inputFile.readSamples(0, (iter * messageBits.length + bit) * blockLengthBlocks, samples);

						double zeroTemp = Tools.autoCorrelationSquares(samples, zeroDelayBlocks);
						zeroAcorr += zeroTemp;
						double oneTemp = Tools.autoCorrelationSquares(samples, oneDelayBlocks);
						oneAcorr += oneTemp;
					}
				}

				messageBits[bit] = oneAcorr < zeroAcorr;
				setProgress((1 + bit) * 100 / messageBits.length);
			}

			Files.write(Paths.get(outputFileName), Tools.toBytes(messageBits));

			if (consoleOut != null) {
				consoleOut.append("Odkodowano wiadomość do pliku " + outputFileName + "\n");
			}

		} catch (FileNotFoundException | UnsupportedWaveFormatException | UnexpectedValueException e) {
			if (consoleOut != null) {
				consoleOut.append(e.toString() + ": ");
				consoleOut.append(e.getMessage() + "\n");
			}
			System.err.println(e.getMessage());
			e.printStackTrace(System.err);
		} catch (IOException e) {
			if (consoleOut != null) {
				consoleOut.append(e.toString() + ": ");
				consoleOut.append(e.getMessage() + "\n");
			}
			System.err.println(e.getMessage());
			e.printStackTrace(System.err);
		}  catch (Exception e) {
			if (consoleOut != null) {
				consoleOut.append(e.toString() + ": ");
				consoleOut.append(e.getMessage() + "\n");
			}
			System.err.println(e.getMessage());
			e.printStackTrace(System.err);
		}

		return null;
	}
}
